package com.cgah

import grails.test.*

import com.cgah.exceptions.ListingNotFoundException
import java.text.SimpleDateFormat

class ListingServiceTests extends AbstractIntegrationTest {

    def static buyer;
    def static seller;
    def static Listing listing;
    def jmsTemplate;

    public void setUp() {
        super.setUp()
        def userRole = com.cgah.Role.findByAuthority(Constants.ROLE_USER) ?: new Role(authority: Constants.ROLE_USER).save(failOnError: true)

         // create users and give them user role
         buyer = User.findByUsername('buyer') ?:
             new Customer(
                     username: "buyer",
                     emailAddress: "buyer@test.com",
                     password: "boooya", //springSecurityService.encodePassword('boooya', null),
                     createdDate: new Date(),
                     enabled: true).save(failOnError: true)
         if (!buyer.getAuthorities().contains(userRole)) {
             UserRole.create(buyer, userRole)
         }


         seller = User.findByUsername('seller') ?:
             new Customer(
                     username: "seller",
                     emailAddress: "seller@test.com",
                     password: "boooya", //springSecurityService.encodePassword('boooya', null),
                     createdDate: new Date(),
                     enabled: true).save(failOnError: true)
         if (!seller.getAuthorities().contains(userRole)) {
             UserRole.create(seller, userRole)
         }
         // create the listing for the seller
         // listing = new Listing(name: "bling bling", startingBidPrice: 10.0, seller: seller, endDateTime: new Date() + 6, createdDateTime: new Date() - 6).save(failOnError: true, flush: true);

    }

    public void tearDown() {
        super.tearDown()
    }

    //S-2: Create a Grails service method that supports creating a new listing (integration test)
    void testSave_ObjectIsPersisted() {
        def listingService = new ListingService();

        params.name = "bling bling"
        params.startingBidPrice =  10.0
        params.endDateTime =  new Date() + 6


        def result = listingService.create(params)
        print "result is:" + result;
        assertEquals("success - size are the same", result.size(), 1);\
        Listing alisting = result.get("listingInstance") //result[0].get("customerInstance");
        // on create the object is not persisted to the DB, hence there is no ID
        assertNull(alisting.id);
        alisting = listingService.save(params, seller.id);
        // on save, the object gets persisted to the DB, hence there is an ID.
        // this should be all we need to do, since the ID is only ever assigned once the object is persisted
        // successfully to the DB AND in theory, no one should be able to set the ID.
        assertNotNull(alisting.id);
    }



    //S-2: Create a Grails service method that supports creating a new listing (integration test)
    void testCreate_ReturnsCorrectObject() {
        def listingService = new ListingService();

        params.name = "bling bling"
        params.startingBidPrice =  10.0
        params.endDateTime =  new Date() + 6


        def result = listingService.create(params)
        print "result is:" + result;
        assertEquals("success - size are the same", result.size(), 1);\
        Listing alisting = result.get("listingInstance") //result[0].get("customerInstance");
        // on create the object is not persisted to the DB, hence there is no ID
        assertNull(alisting.id);
        assertEquals(alisting.name, params.name);
        assertEquals(alisting.startingBidPrice, params.startingBidPrice);
        assertEquals(alisting.endDateTime, params.endDateTime);
    }

    // S-4: The Grails service method for S-2 must validate the sellers username and password before creating the listing (integration test)
    void testCreate_invalidUserNamePassword() {

        def listingService = new ListingService();

        params.name = "bling bling"
        params.startingBidPrice =  10.0
        params.endDateTime =  new Date() + 6



        try {
             Listing listing1 = listingService.create(params)
            def result = listingService.save(listing1, "jane", "wtfuwant")
            fail("expception is expected!");
        } catch (ListingNotFoundException le) {
            assertTrue("passed", true);
        }
    }

    // S-4: The Grails service method for S-2 must validate the sellers username and password before creating the listing (integration test)
    void testCreate_correctUserNamePassword() {

        def listingService = new ListingService();

        params.name = "bling bling"
        params.startingBidPrice =  10.0
        params.endDateTime =  new Date() + 6


        try {
             Listing listing1 = listingService.create(params).get('listingInstance')
            def result = listingService.save(listing1, seller.username, seller.password)
             assertNotNull(result);
        } catch (ListingNotFoundException le) {
            fail("expception was not expected");
        }
    }

    //C-5: Provide a JMS Queue listener that will create a new listing based on XML or JSON specified in an incoming message. (integration test).
    void testCreate_Using_JMS_Queue() {
        def listingService = new ListingService();

        params.name = "bling bling";
        params.startingBidPrice = 10.0
        params.endDateTime = new Date() + 6
        params.description = "blah"
        params.'seller.id' = seller.id;

        Listing l = listingService.create(params).get('listingInstance'); //sdf.parse(params.endDateTime.toString())
        String json = (new grails.converters.JSON(l)).toString();

        jmsTemplate.convertAndSend("com.cgah.listing.queue", json)

        def count = 0;
        // this could give us false negatives but idfc now
        // it's fuking 5 in the morning and i'm tired
        while (true && count < 10) {
            sleep(1000);
            if (null != Listing.findByName( params.name)) {
                break;
            }
            count++;
        }

        if (count == 10) {
            fail("after " + count + " tries, no record in db.  gave up");
        }

     }



}
